#include <stdio.h>
#include <stdlib.h>
#include "dominion.h"
#include "rngs.h"
#include "math.h"
#include <assert.h>
#include <string.h>

void prepRandom(int strm, int seed){
  SelectStream(strm);
  PutSeed((long)seed);
}

int getRandomNumber(int min, int max){
	int number = floor(Random() * (max-min));
	number += min;
	return number;

}

void randomizeSupply(struct gameState *g){
	int i;
	for(i=0; i < 27; i++){
		g->supplyCount[i] = getRandomNumber(0, 40);
	}
}

void randomizeHands(struct gameState *g){
	int players = g->numPlayers;
	int i, j;
	for(i=0; i < players; i++){
		g->handCount[i] = getRandomNumber(0, MAX_HAND);
		for(j = 0; j < g->handCount[i]; j++){
			g->hand[i][j] = getRandomNumber(0, 26);
		}

	}
}

void randomizeDecks(struct gameState *g){
	int players = g->numPlayers;
	int i, j;
	for(i=0; i < players; i++){
		g->deckCount[i] = getRandomNumber(0, MAX_DECK);
		for(j = 0; j < g->deckCount[i]; j++){
			g->deck[i][j] = getRandomNumber(0, 26);
		}

	}
	
}

void randomizeDiscard(struct gameState *g){
	int players = g->numPlayers;
	int i, j;
	for(i=0; i < players; i++){
		g->discardCount[i] = getRandomNumber(0, MAX_DECK);
		for(j = 0; j < g->discardCount[i]; j++){
			g->discard[i][j] = getRandomNumber(0, 26);
		}

	}
	
}
void randomizeTurn(struct gameState *g){
	g->whoseTurn = getRandomNumber(0, g->numPlayers);
}

int makeRandomGameState(struct gameState *g){
//	printf("Randomizing Game\n");
	g->numPlayers = getRandomNumber(2, 4);
	randomizeSupply(g);
	randomizeDecks(g);
	randomizeDiscard(g);
	randomizeHands(g);
	randomizeTurn(g);
	g->coins = getRandomNumber(0, 20);
//	printf("Game Randomized\n");
	return 0;
}

int findCardsInHand(struct gameState *g, int supplyPos, int player){
	int i;
	int cards = 0;
	for(i = 0; i < g->handCount[player]; i++){
		if(g->hand[player][i] == supplyPos){
			cards ++;
		}
	}
	return cards;
}

int findCardsInDeck(struct gameState *g, int supplyPos, int player){
	int i;
	int cards = 0;
	for(i = 0; i < g->deckCount[player]; i++){
		if(g->deck[player][i] == supplyPos){
			cards ++;
		}
	}
	return cards;
}

int findCardsInDiscard(struct gameState *g, int supplyPos, int player){
	int i;
	int cards = 0;
	for(i = 0; i < g->discardCount[player]; i++){
		if(g->discard[player][i] == supplyPos){
			cards ++;
		}
	}
	return cards;
}

int testBuy(struct gameState *g){
//	printf("Testing buy function\n");
	int i;
	struct gameState g22;
	struct gameState *g2 = &g22;
	memcpy (g2, g, sizeof(struct gameState));
//	printf("Game State copied\n");
	int result, inHandAfter, inDeckAfter, inDiscardAfter;
	int supplyPos = getRandomNumber(0, 26);
	int inHandBefore = findCardsInHand(g, supplyPos, g->whoseTurn);
	int inDeckBefore = findCardsInDeck(g, supplyPos, g->whoseTurn);
	int inDiscardBefore = findCardsInDiscard(g, supplyPos, g->whoseTurn);
	result = buyCard(supplyPos, g);
	if(result < 0){
		if(memcmp (g2, g, sizeof(struct gameState)) !=0){
			printf("State changed after unsuccessful purchase!\n");
		}
		return 0;
	}
	else{
		if(g->coins < 0){
			printf("Coins are negative! %d\n", g->coins);
		}
		if(g->discardCount[g->whoseTurn] != (g2->discardCount[g2->whoseTurn]+1)){
			printf("discardCount not correct! before: %d after: %d\n", g->whoseTurn, g2->whoseTurn);
		}
		inHandAfter = findCardsInHand(g, supplyPos, g->whoseTurn);
		inDeckAfter = findCardsInDeck(g, supplyPos, g->whoseTurn);
		inDiscardAfter = findCardsInDiscard(g, supplyPos, g->whoseTurn);
		if(inHandAfter != inHandBefore){
			printf("Hand Changed on purchase! -- card: %d amt before: %d amt after: %d", supplyPos, inHandBefore, inHandAfter);
		}
		if(inDeckAfter != inDeckBefore){
			printf("Deck Changed on purchase! -- card: %d amt before: %d amt after: %d", supplyPos, inDeckBefore, inDeckAfter);
		}
		if((inDiscardBefore +1) != inDiscardAfter){
			printf("Discard not Changed correctly on buy! -- card: %d amt before: %d amt after: %d", supplyPos, inDiscardBefore, inDiscardAfter);
		}
		//test supply
		for(i = 0; i < treasure_map+1; i++){
			if(supplyPos == i){
				if(g->supplyCount[i] != g2->supplyCount[i] - 1){
					printf("SupplyCount not correct! card: %d before: %d after: %d", i, g2->supplyCount[i], g->supplyCount[i]);
				}
			}
			else{
				if(g->supplyCount[i] != g2->supplyCount[i]){
					printf("Wrong card in supply changed! card: %d before: %d after: %d", i, g2->supplyCount[i], g->supplyCount[i]);
				}
			}
		}

	}
	return 1;
}

int main(int argc, char** argv){
	int strm = 1, seed = 4, min = 2, max = 50;
	if(argc > 1){
		strm = atoi(argv[1]);
	}
	if(argc > 2){
		seed = atoi(argv[2]);
	}
	if(argc > 3){
		min = atoi(argv[3]);
	}
	if(argc > 4){
		max = atoi(argv[4]);
	}
	prepRandom(strm, seed);
	int i;
	struct gameState *g = newGame();
	printf("Testing buyCard()\n");
	for(i=0; i < 1000; i++){
		
		makeRandomGameState(g);
		testBuy(g);
		if(i%100 == 0)
			printf("%d, ", i);
	}
	printf("\nTest Complete");

	return 0;
}
